package cn.edu.neu.vmmigeval.cloud.policy;

import cn.edu.neu.vmmigeval.cloud.config.Migration;
import cn.edu.neu.vmmigeval.cloud.entity.*;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by yfwz100 on 16/2/25.
 */
public class VmAllocation {

    public MigratedHostPolicy migratedHost;

    public VmSelectionPolicy vmSelection;

    public VmPlacementPolicy vmPlacement;

    public VmAllocation() {
    }

    public VmAllocation(MigratedHostPolicy migratedHostPolicy, VmSelectionPolicy vmSelectionPolicy,
                        VmPlacementPolicy vmPlacementPolicy) {
        super();
        this.migratedHost = migratedHostPolicy;
        this.vmSelection = vmSelectionPolicy;
        this.vmPlacement = vmPlacementPolicy;
    }

	/*
    public boolean allocateHostForVm1(List<Host> hosts,Vm vm){
		boolean allocation = false;
		if(hosts!=null&&hosts.size()!=0){
			int nums = hosts.size();
			while(true){
				int random = (int)(Math.random()*nums);
				Host host = hosts.get(random);
			for (Host host : hosts) {
				int currentAllocationCpu = 0 ;
				int currentAllocationRam = 0 ;
				int currentAllocationBw = 0 ;
				int currentAllocationDisk = 0 ;
				if(host.getActive()==0){
					for (Vm vmOfHost : host.getVmList()) {
						currentAllocationCpu+=vmOfHost.getTotalCpu();
						currentAllocationRam+=vmOfHost.getTotalRam();
						currentAllocationBw+=vmOfHost.getTotalBw();
						currentAllocationDisk+=vmOfHost.getTotalDisk();
					}
					if(currentAllocationCpu+vm.getTotalCpu()<=host.getTotalCpu()&&
							currentAllocationRam+vm.getTotalRam()<=host.getTotalRam()&&
							currentAllocationBw+vm.getTotalBw()<=host.getTotalBw()&&
							currentAllocationDisk+vm.getTotalDisk()<=host.getTotalDisk()){
						host.getVmList().add(vm);
						vm.setHost(host);
						allocation = true;
						//System.out.println("虚拟机:"+vm.getId()+"被分配到了主机： "+host.getId()+"上了");
						return true;
					}
				}
			}
		}
		if(!allocation){
			for (Host host : hosts) {
				if(host.getActive()==1){
					if(vm.getTotalCpu()<=host.getTotalCpu()&&
							vm.getTotalRam()<=host.getTotalRam()&&
							vm.getTotalBw()<=host.getTotalBw()&&
							vm.getTotalDisk()<=host.getTotalDisk()){
						host.getVmList().add(vm);
						vm.setHost(host);
						//System.out.println("虚拟机:"+vm.getId()+"被分配到了主机： "+host.getId()+"上了");
						return true;
					}
				}
			}
		}
		System.out.println("虚拟机:"+vm.getId()+"无法分配");
		return false;
	}*/

    private List<Migration> migrations;

    public List<Migration> getMigrations() {
        return migrations;
    }

    public void optimizeAllocation(DataCenter dc, int clock) {
        if (clock <= 5) {
            migrations = null;
            return;
        }
        final List<Host> myHosts = dc.getHosts();
        int actives = 0, shutdowns = 0;
        for (Host host : myHosts) {
            if (host.getActive() == 0) {
                actives++;
            } else {
                shutdowns++;
            }
        }
        System.out.println("active is: " + actives + " shutdowns: " + shutdowns);
        List<Migration> totalMigsOfThisPeriod = new ArrayList<Migration>();
        //选取过负载或者低负载的主机
        List<Host> hostsOverUsed = migratedHost.getOverHosts(myHosts);
        List<Host> hostsUnderUsed = migratedHost.getUnderHosts(myHosts);
        List<Host> hosts = new ArrayList<Host>();
        hosts.addAll(hostsOverUsed);
        hosts.addAll(hostsUnderUsed);
        //System.out.println("this is :"+migratedHost);
        if (hosts != null && hosts.size() != 0) {
            System.out.println("过载和底载的个数：" + hosts.size());
        }

        for (Host host : hosts) {
            //System.out.println("overis :"+host.getId());

            //为每台host选取待迁移的虚拟机集合
            List<Vm> vmsToMigrate = vmSelection.getMigratedVmsfromHost(host);
            if (vmsToMigrate != null && !vmsToMigrate.isEmpty()) {
                //System.out.println("有待迁移的虚拟机！");

                List<Migration> migrations = vmPlacement.getNewVmPlacement(vmsToMigrate, myHosts);

                if (migrations != null && migrations.size() != 0) {
                    //System.out.println("dc  "+dc.getMigrationings());
                    dc.getMigrationings().addAll(migrations);
                    totalMigsOfThisPeriod.addAll(migrations);
                }
                //该虚拟机集合如何放置到目标主机上
            }

        }
        System.out.println("迁移个数:" + totalMigsOfThisPeriod.size());
		/*List<Host> hostsUnderUsed = migratedHost.getUnderHosts(myHosts);
		for (Host host : hostsUnderUsed) {
			System.out.println("overis :"+host.getId());
			//为每台host选取待迁移的虚拟机集合
			List<Vm> vmsToMigrate = host.getVmList();//vmSelection.getMigratedVmsfromHost(host);
			List<Migration> migrations = vmPlacement.getNewVmPlacement(vmsToMigrate,myHosts);
			dc.getMigrationings().addAll(migrations);

			totalMigsOfThisPeriod.addAll(migrations);
			//该虚拟机集合如何放置到目标主机上

		}*/
        migrations = totalMigsOfThisPeriod;
    }

    //修改之前的调度方法

    public boolean allocateHostForVm(List<Host> hosts, Vm vm) {
        boolean allocation = false;

        if (hosts != null && hosts.size() != 0) {
            int nums = hosts.size();
            while (true) {
                int random = (int) (Math.random() * nums);
                Host host = hosts.get(random);

                //for (Host host : hosts) {

                int currentAllocationCpu = 0;
                int currentAllocationRam = 0;
                int currentAllocationBw = 0;
                int currentAllocationDisk = 0;

                if (host.getActive() == 0) {

                    for (Vm vmOfHost : host.getVmList()) {
                        currentAllocationCpu += vmOfHost.getTotalCpu();
                        currentAllocationRam += vmOfHost.getTotalRam();
                        currentAllocationBw += vmOfHost.getTotalBw();
                        currentAllocationDisk += vmOfHost.getTotalDisk();
                    }

                    if (currentAllocationCpu + vm.getTotalCpu() <= host.getTotalCpu() &&
                            currentAllocationRam + vm.getTotalRam() <= host.getTotalRam() &&
                            currentAllocationBw + vm.getTotalBw() <= host.getTotalBw() &&
                            currentAllocationDisk + vm.getTotalDisk() <= host.getTotalDisk()) {

                        host.getVmList().add(vm);
                        vm.setHost(host);
                        allocation = true;
                        System.out.println("虚拟机:" + vm.getId() + "被分配到了主机： " + host.getId() + "上了");
                        return true;

                    }
                }
            }


        }
        if (!allocation) {
            for (Host host : hosts) {
                if (host.getActive() == 1) {
                    if (vm.getTotalCpu() <= host.getTotalCpu() &&
                            vm.getTotalRam() <= host.getTotalRam() &&
                            vm.getTotalBw() <= host.getTotalBw() &&
                            vm.getTotalDisk() <= host.getTotalDisk()) {

                        host.getVmList().add(vm);
                        vm.setHost(host);
                        System.out.println("虚拟机:" + vm.getId() + "被分配到了主机： " + host.getId() + "上了");
                        return true;
                    }


                }
            }
        }
        System.out.println("虚拟机:" + vm.getId() + "无法分配");
        return false;
    }

    public MigratedHostPolicy getMigratedHost() {
        return migratedHost;
    }

    public void setMigratedHost(MigratedHostPolicy migratedHost) {
        this.migratedHost = migratedHost;
    }

    public VmSelectionPolicy getVmSelection() {
        return vmSelection;
    }

    public void setVmSelection(VmSelectionPolicy vmSelection) {
        this.vmSelection = vmSelection;
    }


    public VmPlacementPolicy getVmPlacement() {
        return vmPlacement;
    }

    public void setVmPlacement(VmPlacementPolicy vmPlacement) {
        this.vmPlacement = vmPlacement;
    }


}
